home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Music / PLAY / MultiPlayer / NotePlayer / NotePlayer.doc < prev    next >
Text File  |  1995-08-23  |  20KB  |  436 lines

  1.                                 NotePlayer
  2.                            Standard description
  3.                          Copyright 1992 Bryan Ford
  4.                                Version 1.10
  5.  
  6.  
  7.  
  8.                                Distribution
  9.                                ~~~~~~~~~~~~
  10.  
  11.     This package is provided "as is" without warranty of any kind, either
  12. expressed or implied, including, but not limited to, the implied warranty
  13. of fitness for a particular purpose.  All risks associated with the use of
  14. this package are assumed by you.
  15.  
  16.     This package is freely redistributable as long as none of its contents
  17. are modified, added, or removed.  You may not charge more for distributing
  18. it than a small fee to cover the disk copying expenses.  It may not be used
  19. in or distributed with any commercial program without my written
  20. permission.  (If you want to use anything in a commercial program, just ask
  21. me - I probably won't charge anything; I mainly just want to know who is
  22. using it for what.)  The distribution must contain the following files:
  23.  
  24.     NotePlayer.doc      This document
  25.     note.i              Include file used to accessing a NotePlayer
  26.     notesys.asm         System-friendly audio.device NotePlayer
  27.     notehard.asm        Simple hardware-banging NotePlayer
  28.     note.lib            Link library containing assembled versions of
  29.                         notesys.asm and notehard.asm
  30.  
  31.  
  32.  
  33.                                Introduction
  34.                                ~~~~~~~~~~~~
  35.  
  36.     This document describes the NotePlayer standard.  The NotePlayer
  37. standard is an application interface specification designed to be
  38. compatible across all 680x0-based computers.  Its purpose is to allow
  39. hardware-independent music players to be written which can be used in a
  40. variety of environments, operating systems, and even on completely
  41. different computers.  It also makes it easier to simply write music players
  42. for the Amiga.
  43.  
  44.     Note that while this document defines note players rather than music
  45. players, one of the goals is NOT to make NotePlayers interchangeable with
  46. each other.  (This would be pretty much impossible.)  The goal is to make
  47. the interface to a note player standardized, so music players can be
  48. made interchangeable.
  49.  
  50.     A NotePlayer module is a module written to this standard, which
  51. provides facilities to music players for playing notes.  These calls, along
  52. with some timing facilities provided in some other way (such as through the
  53. GMOD standard), provide everything a music player needs to play music. The
  54. interface is very powerful, but at the same time very easy to use for a
  55. music player.
  56.  
  57.     Two example NotePlayer modules for the Amiga have been provided already
  58. (described lager).  For an example of a music player that uses the
  59. NotePlayer standard, see the file "ptsplay.asm" in the MultiPlayer 1.30 (or
  60. later) distribution.  This is a standard Protracker player modified to use
  61. a NotePlayer instead of banging on the hardware directly.  (As a result,
  62. MultiPlayer's Protracker player is one of the friendliest around.)
  63.  
  64.  
  65.  
  66.                              Client interface
  67.                              ~~~~~~~~~~~~~~~~
  68.  
  69.     The only part of a NotePlayer module visible to the music player is a
  70. short jump table.  A particular NotePlayer module is referred to by a
  71. pointer to its jump table.  For example, in a portable GMOD module, a
  72. pointer to the NotePlayer's jump table is given to the module.  The module
  73. then performs all of its low-level note playing through entrypoints in this
  74. jump table.
  75.  
  76.     NotePlayer entrypoints are intended to be called from assembly
  77. language.  Calling them from C or another high-level language may require
  78. some kind of stub routines written in assembly language.  (But who wants to
  79. write music players in C, anyway?)
  80.  
  81.     The parameters to each of the functions in the jump table entries
  82. listed below are passed in registers, as indicated on the second line of
  83. each entry description.  The suffix '.b', '.w', and '.l' indicates which
  84. part of that register the NotePlayer looks at.  For '.b' and '.w', the
  85. NotePlayer ignores the top part of the register - it does not have to
  86. contain zero.
  87.  
  88.     The NotePlayer routines have pretty much standard calling conventions.
  89. They may destroy registers D0-D1/A0-A1, but will save all other registers.
  90. Return codes are returned in D0 where appropriate.
  91.  
  92.     The entries in the jump table are each four bytes long.  The number of
  93. entries in the jump table depends on the version number of the NotePlayer.
  94. The version number of a particular NotePlayer corresponds to the version
  95. number of the NotePlayer.doc (this document) according to which the
  96. NotePlayer was written.  The first eight entrypoints are present in all
  97. NotePlayers.  The currently defined entrypoints are:
  98.  
  99.  
  100. NotePlayer+$00: info = NoteInfo()
  101.                 D0.l
  102.  
  103.     Returns a pointer to an information structure in D0.  The structure's
  104. size depends on the version number in the structure.  The part of the
  105. structure defined in this version of the standard is:
  106.  
  107.     info+$00 (byte) Version number of NotePlayer standard used
  108.     info+$01 (byte) Revision number of this particular NotePlayer
  109.     info+$02 (byte) General-purpose flags:
  110.         bit 0: All sound samples must be in MEMF_CHIP
  111.         bit 1: Amiga "period" extension supported (described later)
  112.     info+$03 (byte) Maximum number of channels this NotePlayer supports
  113.     info+$04 (long) Pointer to name of this particular NotePlayer module
  114.  
  115.  
  116. NotePlayer+$04: errmsg = NoteInit(channels,stereoarray)
  117.                  D0.l               D0.b       A0.l
  118.  
  119.     Gets the NotePlayer ready to play notes.  This must be called before
  120. any other entrypoints are called.  (Exceptions:  NoteInfo and NoteFinish
  121. may be called before NoteInit.)
  122.  
  123.     The client passes the number of (monophonic) channels it will need in
  124. D0, and an array describing the preferred stereo orientation of each
  125. channel in A0.  The client can ask for between 1 and 128 channels, but if
  126. it asks for more channels than the NotePlayer supports, NoteInit will fail
  127. and the client will not be able to use this NotePlayer to play its music.
  128.  
  129.     The stereoarray, if supplied, must contain as many bytes as the number
  130. of channels requested. The first byte describes channel 0, the second byte
  131. channel 1, and so on.  Each byte contains a signed value from -127 to 127
  132. (-128 is reserved and should not be used) describing "where" this channel
  133. is supposed to play.  A value of -127 indicates far left; 127 indicates far
  134. right; 0 indicates center (no stereo).  Other values in this range may be
  135. used as a balance control, indicating the position on a gradient between
  136. left and right, although most NotePlayers will simply look at whether the
  137. byte is negative, positive, or zero.  (Future hot-shot NotePlayers running
  138. on advanced sound hardware can use two hardware channels per client-visible
  139. channel to achieve smooth stereo panning; a future version of this standard
  140. will provide for this situation when it arises.)  If the client passes NULL
  141. for the stereoarray, an array full of zeros is assumed.
  142.  
  143.     NoteInit returns zero if the NotePlayer was successfully initialized;
  144. it returns a pointer to a null-terminated error message if initialization
  145. failed for some reason or another.  If the call is successful, the client
  146. may commence playing notes with the NotePlayer, and must call NoteFinish
  147. when it is done.  If the call fails, the client must not call any other
  148. NotePlayer entrypoints except the first three, and it does not need to
  149. (though it may) call NoteFinish.
  150.  
  151.  
  152. NotePlayer+$08: NoteFinish()
  153.  
  154.  
  155.     This call stops all currently playing notes and performs whatever
  156. internal cleanup is necessary when note playing is finished.  If the
  157. NoteInit call succeeded, the client must call this entrypoint when it is
  158. finished with the NotePlayer.
  159.  
  160.  
  161. NotePlyaer+$0c: NoteStart(chan,oneshotdata,oneshotlen,repdata,replen,freq,vol)
  162.                           D2.b      A0.l       D0.l     A1.l   D1.l  D3.w D4.w
  163.  
  164.     This entrypoint is the workhorse of the NotePlayer system: it plays
  165. notes.  Any note previously playing in the channel is stopped, and a new
  166. note is started.
  167.  
  168.     The channel number must be between 0 and n-1, where n is the number of
  169. channels requested in (and granted by) the NoteInit call.  If bit 7 in the
  170. channel number is set, the NotePlayer takes the logical NOT of the
  171. parameter as the real channel number, and modifies the behavior of the call
  172. slightly.  In this case, instead of stopping any currently playing note and
  173. starting the new note immediately, the change is made after the currently
  174. playing note finishes its current cycle: when it is about to start the
  175. repeat part, either directly after the one-shot part finishes, or when the
  176. current repeat cycle is finished.  The new note will effectively be
  177. "joined" to the old note, making it possible to implement "release" phases
  178. of notes, among other things.
  179.  
  180.     If oneshotlen is nonzero, then it contains the number of 8-bit samples
  181. in the one-shot part of the note, and oneshotdata points to the sample
  182. data.  If oneshotlen is zero, the note has no one-shot part, and the repeat
  183. part (if it exists) is started immediately.
  184.  
  185.     The replen and repdata parameters work exactly like the one-shot
  186. parameters.  If repdata is zero, the note has no repeat part, and the
  187. channel will become silent as soon as the one-shot part is finished.
  188.  
  189.     If both oneshotlen and replen are zero, then any currently playing note
  190. is stopped without starting a new note.  This is equivalent in effect to
  191. the NoteStop entrypoint.
  192.  
  193.     The freq parameter contains the sampling frequency at which to play the
  194. note, in Hz.  The vol parameter contains the volume at which to play the
  195. note, ranging from $000 (silent) to $100 (maximum).
  196.  
  197.     If flag bit 1 in the Info structure returned by NoteInfo is set, then a
  198. special extension to the frequency specification is supported, to allow
  199. Amiga-based "tracker" players to be more easily accomodated.  If the client
  200. calls NoteStart with D3.w (freq) set to zero, then the frequency is defined
  201. by an Amiga period value in the high word of D3.  To calculate frequency
  202. from period, or vice versa, simply divide the known value into 3579545.
  203.  
  204.  
  205. NotePlayer+$10: NoteStop(chan)
  206.                          D2.b
  207.  
  208.     Stops any note currently playing in the specified channel, either
  209. immediately (if D2.b contains a normal channel number from 0-127), or after
  210. the current cycle of the currently playing note is finished (if D2.b
  211. contains a NOTed channel number).  This call is equivalent to calling
  212. NoteStart with zero in both oneshotlen and replen.
  213.  
  214.  
  215. NotePlayer+$14: NoteFreqVol(chan,freq,vol)
  216.                             D2.b D3.w D4.w
  217.  
  218.     Changes the frequency and volume of the currently playing note, either
  219. immediately (if D2.b contains a normal channel number from 0-127), or after
  220. the current cycle is finished (if D2.b contains a NOTed channel number).
  221. This entrypoint is used to implement slides and fades and such.  The freq
  222. and vol parameters work exactly as they do in the NoteStart entrypoint.
  223.  
  224.  
  225. NotePlayer+$18: NoteFreq(chan,freq)
  226.                          D2.b D3.w
  227.  
  228.     Changes the frequency of the currently playing note, without changing the
  229. volume.  Otherwise works exactly the same way as NoteFreqVol.
  230.  
  231.  
  232. NotePlayer+$1c: NoteVol(chan,vol)
  233.                         D2.b D4.w
  234.  
  235.     Changes the volume of the currently playing note, without changing the
  236. frequency.  Otherwise works exactly the same way as NoteFreqVol.
  237.  
  238.  
  239.  
  240.  
  241.               Amiga system-friendly NotePlayer (notesys.asm)
  242.               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  243.  
  244.     The file "notesys.asm" contains a sample NotePlayer module for the
  245. Amiga which uses the audio.device to play notes.  To use it, simply link
  246. "note.lib" with your program.  The symbol "NoteSys" then points to the
  247. NotePlayer jump table.  (The symbol "_NoteSys" also points to the jump
  248. table, for high-level language users.)
  249.  
  250.     Since this NotePlayer uses the audio.device for everything it does, it
  251. may be somewhat slower than a player that accesses the hardware directly.
  252. However, as the programmers at Commodore have pointed out many times, using
  253. the audio.device means there is no need for ugly DMA-delay loops and such,
  254. which often compensates for the slightly lower efficiency of the
  255. audio.device.  Moreover, this NotePlayer can give up audio channels as
  256. needed, and it automatically re-allocates them when they again become
  257. available, thus allowing beeps and such to be heard through the music.
  258.  
  259.     This NotePlayer includes a master volume/balance control which is
  260. completely independent of the main NotePlayer interface.  (In other words,
  261. the music player can't use it - instead, the main program that's
  262. responsible for putting the NotePlayer and the music player together uses
  263. it.)  To set the master volume, call the NoteSysMasterVol function:
  264.  
  265.     NoteSysMasterVol(volume)
  266.                       D0.w
  267.  
  268.     This function is available in both assembly ("NoteSysMasterVol") and C
  269. ("_NoteSysMasterVol" for stack args, "@NoteSysMasterVol" for register
  270. args).  The volume parameter must be between 0 and $100 (256).  If any
  271. music is currently playing, the volume changes immediately.  The master
  272. volume cannot be changed in any way through calls to the entrypoints in the
  273. normal (music player-visible) jump table.
  274.  
  275.     If you want separate control of the volume of the left and right
  276. channels (i.e. for a balance control), use the NoteSysMasterVolBal
  277. function:
  278.  
  279.     NoteSysMasterVolBal(leftvolume,rightvolume)
  280.                             D0.w       D1.w
  281.  
  282.     This function is also available in assembly and C forms.
  283.  
  284.     "notesys.asm" can be assembled with A68k version 2.71.
  285.  
  286.     You can specify the priority level for audio channel allocation with
  287. the NoteSysAudioPri function:
  288.  
  289.     NoteSysAudioPri(newpri)
  290.                      D0.b
  291.  
  292.     This priority will be applied to all future audio channel allocations.
  293.  
  294.  
  295.  
  296.              Amiga hardware-banging NotePlayer (notehard.asm)
  297.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  298.  
  299.     For situations where the audio.device isn't available, is too slow, or
  300. simply isn't in style, "notehard.asm" can be used instead for 4-channel
  301. playing.  This module is much smaller and (if you arrange it so DMA delay
  302. loops aren't needed) faster, although not exactly system-friendly.
  303.  
  304.     The NotePlayer jump table in "notehard.asm" works exactly the same way
  305. as in "notesys.asm", except it's externally defined as "NoteHard" (and
  306. "_NoteHard") instead of "NoteSys".
  307.  
  308.     For simplicity, the NoteInit call in this NotePlayer does no error
  309. checking.  In particular, it doesn't check the number of channels requested
  310. by the music player.  If the music player requests more than four channels,
  311. NoteInit will succeed, but the first time the music player tries to use
  312. channel number 4 or higher, Bad Things will happen.
  313.  
  314.     This NotePlayer imposes a few restrictions, for the sake of simplicity.
  315. First, the sync-cycle feature (activated by NOTing the channel number) is
  316. not supported.  Do not hook a music player that uses it to this NotePlayer,
  317. or your results will be Not Good.
  318.  
  319.     Second, this NotePlayer doesn't handle samples more than 64K in size.
  320.  
  321.     Third, it assumes that the first four bytes in chip memory (at absolute
  322. address 0) contain zero.  This is normally the case anyway, and it is easy
  323. to enforce in a game or demo that takes over the machine either temporarily
  324. or permanently.
  325.  
  326.     Finally, unlike "notesys.asm" (and any other full-featured NotePlayer,
  327. "notehard.asm" does no mapping of channels; it does not attempt to match
  328. hardware channels with client channels according to the stereo preferences
  329. specified in the NoteInit call.  The client's channel 0 goes to hardware
  330. channel 0, etc.
  331.  
  332.     This NotePlayer does not need any of the audio interrupts, and you
  333. should have them all turned off (or redirected to a harmless routine) when
  334. you use it.
  335.  
  336.     The DMA delay, of course, is the bane of all Amiga players.
  337. "notehard.asm" requires that the client (not the music player, but the
  338. program that hooks the music player and the NotePlayer together) handle DMA
  339. waiting, for maximum flexibility.  After the music player finishes all its
  340. activity for a certain cycle (probably including calls to NoteStart) and
  341. returns to the client, the client must check the longword named
  342. "NoteHardDMACall" (or "_NoteHardDMACall"), which is defined in
  343. "notehard.asm".  If this longword is nonzero, it is a pointer to a routine
  344. which must be called after waiting an appropriate amount of time (usually
  345. about 7 scanlines).  The routine obeys standard Amiga calling conventions:
  346. it can munch d0-d1/a0-a1, but saves all other registers.  After the routine
  347. returns, the client must again check "NoteHardDMACall" and if it's still
  348. nonzero, wait again and call the new address, and so on until it returns
  349. zero.
  350.  
  351.     As an example, if you can't implement full interrupt-driven DMA
  352. waiting, this scrap of code could do the trick:
  353.  
  354.         bsr     musciplayer
  355. 1$      move.l  NoteHardDMACall,d0
  356.         bz      9$
  357.         move.l  d0,a0
  358.         moveq   #7-1,d1
  359. 2$      move.b  $dff006,d0
  360. 3$      cmp.b   $dff006,d0
  361.         beq.s   3$
  362.         dbra    d1,2$
  363.         jsr     (a0)
  364.         bra     1$
  365. 9$
  366.  
  367.     Of course, playing music will hog a lot less CPU time if you use a CIA
  368. timer interrupt for this purpose.
  369.  
  370.     As a final reminder, this NotePlayer never accesses the operating
  371. system or anything.  The only things it accesses (outside of some internal
  372. variables) are the DMACON register and the audio registers ($dff0a0 to
  373. $dff0d8).
  374.  
  375.     If you (heaven forbid!) want to use this routine while the OS is
  376. around, you'd better open the audio.device yourself and lock all the
  377. channels so things don't go haywire if someone else tries to access the
  378. audio hardware at the same.
  379.  
  380.     "notehard.asm" can be assembled with A68k version 2.71.
  381.  
  382.  
  383.  
  384.                                Future plans
  385.                                ~~~~~~~~~~~~
  386.  
  387.     In the future I hope to write more NotePlayers to be distributed in
  388. this package.  Among them:
  389.  
  390.     * A better hardware NotePlayer that supports sound effects and such.
  391.  
  392.     * An 8-channel NotePlayer.
  393.  
  394.     * NotePlayers for the new sound boards for the Amiga.
  395.  
  396.     It would also be nice to see NotePlayers written for other 680x0-based
  397. computers besides the Amiga.  This could be very handy for games and other
  398. programs which are often written for several computers at once.
  399.  
  400.  
  401.  
  402.                               Version History
  403.                               ~~~~~~~~~~~~~~~
  404.  
  405. 1.10 (R3, 14-Sep-92)
  406.         Added NoteSysAudioPri function to notesys.asm, to allow the client
  407.             to specify the audio channel allocation priority.
  408.  
  409. 1.01 (R2, 25-May-92)
  410.         Removed 'ptplay.asm' from the NotePlayer distribution, since it
  411.             can now be gotten in its "native" environment with MultiPlayer.
  412.  
  413. 1.00 (R1, 5-May-92)
  414.         First release.
  415.  
  416.  
  417.  
  418.                               Contact Address
  419.                               ~~~~~~~~~~~~~~~
  420.  
  421.     I tend to move around a great deal, so mail sent directly to me
  422. sometimes has a hard time catching up.  If you want mail to reach me (it
  423. may take a while, but it WILL reach me), send it to this address:
  424.  
  425.         Bryan Ford
  426.         8749 Alta Hills Circle
  427.         Sandy, UT 84093
  428.  
  429.     I can be reached more quickly (for the time being anyway) on the phone
  430. or through one of the electronic mail addresses below:
  431.  
  432.         (801) 944-1990
  433.         baford@peruvian.utah.edu
  434.  
  435.  
  436.